/*
 * $Id: object.h 315 2010-03-25 23:57:03Z cmtonkinson@gmail.com $
 *
 * This file is part of the Symphony project <http://code.google.com/p/symphonymud/>
 * Copyright 2005-2010 Chris Tonkinson <cmtonkinson@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef H_SYMPHONY_OBJECT
#define H_SYMPHONY_OBJECT

#include <list>
#include <set>
#include "compound.h"
#include "identifiers.h"
#include "modifier.h"
#include "mysql.h"

class ObjArmor;
class ObjClothing;
class ObjContainer;
class ObjFood;
class ObjFurniture;
class ObjJewelry;
class ObjKey;
class ObjTrash;
class ObjWeapon;

class Object {
  public:
    // constructors...
    Object( void );
    Object( const Object& ref );
    Object( ROW row );
    ~Object( void );

    // constants...
    enum Type { Type_Undefined = 0, Type_Armor, Type_Clothing, Type_Container, Type_Food, Type_Furniture, Type_Jewelry, Type_Key, Type_Trash, Type_Weapon };
    enum Wearable { Wearable_Undefined = 0, Wearable_Head, Wearable_Ear, Wearable_Face, Wearable_Neck, Wearable_Shoulders, Wearable_Arms, Wearable_Torso, Wearable_Forearm, Wearable_Wrist, Wearable_Hands, Wearable_Hold, Wearable_Finger, Wearable_Waist, Wearable_Legs, Wearable_Knee, Wearable_Shin, Wearable_Ankle, Wearable_Feet };
    enum Flags {  Flag_Undefined = 0, Flag_Noremove = A, Flag_Nodrop = B, Flag_Noget = C, Flag_Meltdrop = D, Flag_Glowing = E, Flag_Humming = F, Flag_Burnproof = G };

    // public accessors
    void                        ID( const unsigned long& ID )         { _ID = ID; }
    unsigned long               ID( void ) const                      { return _ID; }
    void                        type( const Type& type );
    void                        type( const Type& type, ROW row );
    void                        type( const Type& type, void* extra_ptr );
    Type                        type( void ) const                    { return _type; }
    void                        vnum( const unsigned long& vnum )     { _vnum = vnum; }
    unsigned long               vnum( void ) const                    { return _vnum; }
    void                        flags( const unsigned long& flags )   { _flags = flags; }
    unsigned long               flags( void ) const                   { return _flags; }
    Identifiers&                identifiers( void )                   { return _identifiers; }
    const Identifiers&          identifiers( void ) const             { return _identifiers; }
    std::set<Compound*>&        composition( void )                   { return _composition; }
    const std::set<Compound*>&  composition( void ) const             { return _composition; }
    void                        level( const unsigned short& level )  { _level = level; }
    unsigned short              level( void ) const                   { return _level; }
    void                        value( const unsigned short& value )  { _value = value; }
    unsigned short              value( void ) const                   { return _value; }
    void                        wearable( const Wearable& wearable )  { _wearable = wearable; }
    Wearable                    wearable( void ) const                { return _wearable; }
    std::list<Modifier*>&       modifiers( void )                     { return _modifiers; }
    const std::list<Modifier*>& modifiers( void ) const               { return _modifiers; }
    void                        extra( void* extra )                  { _extra = extra; }
    void*                       extra( void ) const                   { return _extra; }

    // general methods
    bool          isArmor( void ) const     { return _type == Type_Armor; }
    bool          isClothing( void ) const  { return _type == Type_Clothing; }
    bool          isContainer( void ) const { return _type == Type_Container; }
    bool          isFood( void ) const      { return _type == Type_Food; }
    bool          isFurniture( void ) const { return _type == Type_Furniture; }
    bool          isJewelry( void ) const   { return _type == Type_Jewelry; }
    bool          isKey( void ) const       { return _type == Type_Key; }
    bool          isTrash( void ) const     { return _type == Type_Trash; }
    bool          isWeapon( void ) const    { return _type == Type_Weapon; }

    ObjArmor*     armor( void ) const       { return (ObjArmor*)_extra; }
    ObjClothing*  clothing( void ) const    { return (ObjClothing*)_extra; }
    ObjContainer* container( void ) const   { return (ObjContainer*)_extra; }
    ObjFood*      food( void ) const        { return (ObjFood*)_extra; }
    ObjFurniture* furniture( void ) const   { return (ObjFurniture*)_extra; }
    ObjJewelry*   jewelry( void ) const     { return (ObjJewelry*)_extra; }
    ObjKey*       key( void ) const         { return (ObjKey*)_extra; }
    ObjTrash*     trash( void ) const       { return (ObjTrash*)_extra; }
    ObjWeapon*    weapon( void ) const      { return (ObjWeapon*)_extra; }

    void          flag( const Flags& which, const bool& value ) { flags( value ? (flags()|which) : (flags()&~which) ); }
    bool          flag( const Flags& which ) const              { return (flags()&which) == (unsigned)which; }
    void          flag( const std::string& which, const bool& value );
    const char*   listFlags( void ) const;

    const char*   typeToString( void ) const;
    void          stringToType( const std::string& src );
    const char*   wearableToString( void ) const;
    void          stringToWearable( const std::string& src );

    std::string   serializeModifiers( void ) const;
    void          unserializeModifiers( const std::string& ser );
    std::string   implodeComposition( std::string glue = " " ) const;
    std::string   decorativeShortname( void ) const;
    std::string   decorativeLongname( void ) const;
    std::string   listDecorativeFlags( void ) const;
    std::string   printStatus( void ) const;

    void          insert( Mysql* db, const unsigned long& areaID );
    void          update( Mysql* db ) const;
    void          destroy( Mysql* db ) const;
    void          saveInstance( Mysql* db, const std::string& placement, const unsigned long& id, const unsigned& location, const unsigned & order, char* hash = NULL ) const;

  private:
    // data
    unsigned long         _ID;
    Type                  _type;
    unsigned long         _vnum;
    unsigned long         _flags;
    Identifiers           _identifiers;
    std::set<Compound*>   _composition;
    unsigned short        _level;
    unsigned short        _value;
    Wearable              _wearable;
    std::list<Modifier*>  _modifiers;
    void*                 _extra;

    // methods
    void  deleteExtra( void );
};

#endif // H_SYMPHONY_OBJECT
